﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Net.NetworkInformation;
using Microsoft.Win32;
using System.Resources;
using System.Threading;
using System.Net;

namespace AeXDynSendInventory
{
    public partial class AexDynService : ServiceBase
    {
        public int DelayInSeconds
        {
            get
            {
                return Properties.Settings.Default.DelayInSeconds;
            }
        }
        public AexDynService()
        {
            InitializeComponent();

            NetworkChange.NetworkAddressChanged += (netChangeObj, netChangeEvt) =>
                {
                    try
                    {
                        if (!IsNotificationServerVisible()) return;
                        WriteEventLog(Properties.Resources.EvtIPAddressChanged.Replace("{0}", DelayInSeconds.ToString()), EventLogEntryType.Information);
                        Thread.Sleep(DelayInSeconds * 1000); //Sleep for N seconds until all network states settle
                        SendBasicInventory();
                    }
                    finally
                    {

                    }

                };
        }

        /// <summary>
        /// Returns the Altiris Agents installation directory
        /// </summary>
        /// <value>Instalation Directory</value>
        private string AltirisAgentLocation
        {
            get
            {
                try
                {
                    return Registry.GetValue(Properties.Resources.InstallDirectoryKey, Properties.Resources.InstallDirectoryValue, null) as string;
                }
                catch (Exception ex) { return null; }
            }
        }

        private string AltirisServerName
        {
            get
            {
                try
                {
                    return Registry.GetValue(Properties.Resources.ServersKey, null, null) as string;
                }
                catch (Exception ex) { return null; }
            }
        }

        private string AltirisServerWeb
        {
            get
            {
                try
                {
                    return Registry.GetValue(Properties.Resources.ServersKey + @"\" + AltirisServerName, Properties.Resources.ServerWebValue, null) as string;
                }
                catch (Exception ex) { return null; }
            }
        }

        protected override void OnStart(string[] args)
        {
            WriteEventLog(Properties.Resources.EvtStartingService, EventLogEntryType.Information);
        }

        protected override void OnStop()
        {
            WriteEventLog(Properties.Resources.EvtStoppingService, EventLogEntryType.Information);
        }

        /// <summary>
        /// Calls the Altiris "Send Basic Inventory" method
        /// </summary>
        private void SendBasicInventory()
        {
            if (AltirisAgentLocation == null)
            {
                WriteEventLog(Properties.Resources.EvtAgentLocationError, EventLogEntryType.Warning);
                return; //If Altiris Agent location exists continue
            }

            try
            {
                string AgentUtilityExe = AltirisAgentLocation + @"\AexAgentUtil.exe";
                System.Diagnostics.Process.Start(AgentUtilityExe, "/SendBasicInventory");
            }
            catch (Exception ex)
            {

            }
        }

        /// <summary>
        /// Writes to the event log if WriteEvents True
        /// </summary>
        private void WriteEventLog(string message, EventLogEntryType type)
        {
            string eventLog = Properties.Resources.EventLog;
            string eventSource = Properties.Resources.EventSource;

            if (!EventLog.SourceExists(eventSource))
                EventLog.CreateEventSource(eventSource, eventLog);

            EventLog.WriteEntry(eventSource, message, type);

        }

        /// <summary>
        /// Checks to see see if the computer can communicate with the notification server
        /// </summary>
        /// <returns>
        /// True if computer is able to communicate with the notification server. Attempts to communicate with the server in the following order escalating on failure:
        ///  1. Ping NS Server
        ///  2. Connect via http/https
        /// </returns>
        private bool IsNotificationServerVisible()
        {
            if (ValidateUsingPing()) return true;
            if (ValidateUsingHttp()) return true;
            return false;
        }
        bool ValidateUsingPing()
        {
            try
            {
                Ping ping = new Ping();
                PingReply reply = ping.Send(AltirisServerName);
                if (reply.Status != IPStatus.Success) return false; //assume ping is blocked by the firewall

                WriteEventLog(Properties.Resources.EvtValidatedConnectionViaPing, EventLogEntryType.Information);
                return true;
            }
            catch (Exception ex) { return false; }
        }

        bool ValidateUsingHttp()
        {
            try
            {
                //attempt to validate connection to the server via HTTP
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(AltirisServerWeb);
                request.Timeout = Properties.Settings.Default.WebRequestTimeoutInSeconds * 1000;
                request.Credentials = CredentialCache.DefaultNetworkCredentials;
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                if (response.StatusCode == HttpStatusCode.OK)
                {
                    WriteEventLog(Properties.Resources.EvtValidatedConnectionViaHttp, EventLogEntryType.Information);
                    return true;
                }
                return false;
            }
            catch (Exception ex) { return false; }
        }

    }
}
